home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / comm / tcp / amitcptelnetf.lha / amitcp_telnet+ftp / ftp / cmds.c < prev    next >
C/C++ Source or Header  |  1993-07-31  |  39KB  |  2,189 lines

  1. /*
  2.  * Copyright (c) 1985, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)cmds.c    5.18 (Berkeley) 4/20/89";
  20. #endif /* not lint */
  21.  
  22. /*
  23.  * FTP User Program -- Command Routines.
  24.  */
  25. #include <sys/param.h>
  26. //#include <sys/wait.h>
  27. #include <sys/stat.h>
  28. #include <sys/socket.h>
  29. #ifdef AMI_TCP
  30. #include <bsdsocket.h>
  31. #else
  32. #include <ss/socket.h>
  33. #endif
  34.  
  35. #include <arpa/ftp.h>
  36.  
  37. #include <signal.h>
  38. #include <stdio.h>
  39. #include <errno.h>
  40. #include <netdb.h>
  41. #include <ctype.h>
  42. #include <time.h>
  43. #include <netinet/in.h>
  44. //#include <syslog.h>
  45. #include <fcntl.h>
  46. #ifdef __SASC
  47. #include <ios1.h>
  48. #endif
  49.  
  50. #include "ftp_var.h"
  51.  
  52. extern    char *globerr;
  53. extern    char **glob();
  54. extern    char *home;
  55. extern    char *remglob();
  56. extern    char *mygetenv();
  57. extern    int allbinary;
  58. extern off_t restart_point;
  59. extern char reply_string[];
  60.  
  61. char *mname;
  62. jmp_buf jabort;
  63. char *dotrans(), *domap();
  64.  
  65. bang()
  66. {
  67.     FILE *fp;
  68.     char *pager;
  69.     char command[128];
  70.     char fname[128];
  71.  
  72.     joinpath(fname, dldir, ".temp");
  73.     fp = fopen(fname,"r");
  74.     if (fp != NULL) 
  75.     {
  76.         fclose(fp);
  77.         fp = stdin;
  78.         if ((pager = mygetenv("PAGER")) == 0)
  79.             pager = "more";
  80.         sprintf(command,"%s %s",pager, fname);
  81. #ifdef __SASC
  82.         SetMode(chkufb(fileno(fp))->ufbfh,1L);
  83.         System(command,0L);
  84.         SetMode(chkufb(fileno(fp))->ufbfh,0L);
  85. #else
  86.         SetMode(_devtab[fileno(fp)].fd,1L);
  87.         System(command,0L);
  88.         SetMode(_devtab[fileno(fp)].fd,0L);
  89. #endif
  90.     }
  91. }
  92.  
  93. /*
  94.  * Connect to peer server and
  95.  * auto-login, if possible.
  96.  */
  97. setpeer(argc, argv)
  98.     int argc;
  99.     char *argv[];
  100. {
  101.     char *host, *hookup();
  102.     short port;
  103.  
  104.     if (connected) {
  105.         printf("Already connected to %s, use close first.\n",
  106.             hostname);
  107.         code = -1;
  108.         return;
  109.     }
  110.     if (argc < 2) {
  111.         (void) strcat(line, " ");
  112.         printf("Enter site address: ");
  113.         (void) gets(&line[strlen(line)]);
  114.         makeargv();
  115.         argc = margc;
  116.         argv = margv;
  117.     }
  118.     if (argc > 3) {
  119.         printf("usage: %s host-name [port]\n", argv[0]);
  120.         code = -1;
  121.         return;
  122.     }
  123.     port = sp->s_port;
  124.     if (argc > 2) {
  125.         port = atoi(argv[2]);
  126.         if (port <= 0) {
  127.             printf("%s: bad port number-- %s\n", argv[1], argv[2]);
  128.             printf ("usage: %s host-name [port]\n", argv[0]);
  129.             code = -1;
  130.             return;
  131.         }
  132.         port = htons(port);
  133.     }
  134.     host = hookup(argv[1], port);
  135.     if (host) {
  136.         int overbose;
  137.  
  138.         connected = 1;
  139.         if (autologin)
  140.             (void) login(argv[1]);
  141.     }
  142. }
  143.  
  144. struct    types {
  145.     char    *t_name;
  146.     char    *t_mode;
  147.     int    t_type;
  148.     char    *t_arg;
  149. } types[] = {
  150.     { "ascii",    "A",    TYPE_A,    0 },
  151.     { "binary",    "I",    TYPE_I,    0 },
  152.     { "image",    "I",    TYPE_I,    0 },
  153.     0
  154. };
  155.  
  156. /*
  157.  * Set transfer type.
  158.  */
  159. settype(argc, argv)
  160.     char *argv[];
  161. {
  162.     register struct types *p;
  163.     int comret;
  164.  
  165.     if (argc > 2) {
  166.         char *sep;
  167.  
  168.         printf("usage: %s [", argv[0]);
  169.         sep = " ";
  170.         for (p = types; p->t_name; p++) {
  171.             printf("%s%s", sep, p->t_name);
  172.             if (*sep == ' ')
  173.                 sep = " | ";
  174.         }
  175.         printf(" ]\n");
  176.         code = -1;
  177.         return;
  178.     }
  179.     if (argc < 2) {
  180.         printf("Using %s mode to transfer files.\n", typename);
  181.         code = 0;
  182.         return;
  183.     }
  184.     for (p = types; p->t_name; p++)
  185.         if (strcmp(argv[1], p->t_name) == 0)
  186.             break;
  187.     if (p->t_name == 0) {
  188.         printf("%s: unknown mode\n", argv[1]);
  189.         code = -1;
  190.         return;
  191.     }
  192.     if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
  193.         comret = command ("TYPE %s %s", p->t_mode, p->t_arg);
  194.     else
  195.         comret = command("TYPE %s", p->t_mode);
  196.     if (comret == COMPLETE) {
  197.         (void) strcpy(typename, p->t_name);
  198.         type = p->t_type;
  199.     }
  200. }
  201.  
  202. char *stype[] = {
  203.     "type",
  204.     "",
  205.     0
  206. };
  207.  
  208. /*
  209.  * Set binary transfer type.
  210.  */
  211. /*VARARGS*/
  212. setbinary()
  213. {
  214.     stype[1] = "binary";
  215.     settype(2, stype);
  216. }
  217.  
  218. /*
  219.  * Set ascii transfer type.
  220.  */
  221. /*VARARGS*/
  222. setascii()
  223. {
  224.     stype[1] = "ascii";
  225.     settype(2, stype);
  226. }
  227.  
  228. setebcdic()
  229. {
  230.     setbinary();
  231. }
  232.  
  233. settenex()
  234. {
  235.     setbinary();
  236. }
  237.  
  238. /*
  239.  * Set file transfer mode.
  240.  */
  241. /*ARGSUSED*/
  242. setmode(argc, argv)
  243.     char *argv[];
  244. {
  245.  
  246.     printf("We only support %s mode, sorry.\n", modename);
  247.     code = -1;
  248. }
  249.  
  250. /*
  251.  * Set file transfer format.
  252.  */
  253. /*ARGSUSED*/
  254. setform(argc, argv)
  255.     char *argv[];
  256. {
  257.  
  258.     printf("We only support %s format, sorry.\n", formname);
  259.     code = -1;
  260. }
  261.  
  262. /*
  263.  * Set file transfer structure.
  264.  */
  265. /*ARGSUSED*/
  266. setstruct(argc, argv)
  267.     char *argv[];
  268. {
  269.  
  270.     printf("We only support %s structure, sorry.\n", structname);
  271.     code = -1;
  272. }
  273.  
  274. /*
  275.  * Send a single file.
  276.  */
  277. put(argc, argv)
  278.     int argc;
  279.     char *argv[];
  280. {
  281.     char *cmd;
  282.     int loc = 0;
  283.     char *oldargv1, *oldargv2;
  284.  
  285.     if (argc == 2) {
  286.         argc++;
  287.         argv[2] = argv[1];
  288.         loc++;
  289.     }
  290.     if (argc < 2) {
  291.         (void) strcat(line, " ");
  292.         printf("(local-file) ");
  293.         (void) gets(&line[strlen(line)]);
  294.         makeargv();
  295.         argc = margc;
  296.         argv = margv;
  297.     }
  298.     if (argc < 2) {
  299. usage:
  300.         printf("usage:%s local-file remote-file\n", argv[0]);
  301.         code = -1;
  302.         return;
  303.     }
  304.     if (argc < 3) {
  305.         (void) strcat(line, " ");
  306.         printf("(remote-file) ");
  307.         (void) gets(&line[strlen(line)]);
  308.         makeargv();
  309.         argc = margc;
  310.         argv = margv;
  311.     }
  312.     if (argc < 3) 
  313.         goto usage;
  314.     oldargv1 = argv[1];
  315.     oldargv2 = argv[2];
  316.     if (!globulize(&argv[1])) {
  317.         code = -1;
  318.         return;
  319.     }
  320.     /*
  321.      * If "globulize" modifies argv[1], and argv[2] is a copy of
  322.      * the old argv[1], make it a copy of the new argv[1].
  323.      */
  324.     if (argv[1] != oldargv1 && argv[2] == oldargv1) {
  325.         argv[2] = argv[1];
  326.     }
  327.     cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR");
  328.     if (loc && ntflag) {
  329.         argv[2] = dotrans(argv[2]);
  330.     }
  331.     if (loc && mapflag) {
  332.         argv[2] = domap(argv[2]);
  333.     }
  334.     sendrequest(cmd, argv[1], argv[2],
  335.         argv[1] != oldargv1 || argv[2] != oldargv2);
  336. }
  337.  
  338. #if 0
  339. /*
  340.  * Send multiple files.
  341.  */
  342. mput(argc, argv)
  343.     char *argv[];
  344. {
  345.     register int i;
  346.     int ointer;
  347.     sig_t (*oldintr)(), mabort();
  348.     extern jmp_buf jabort;
  349.     char *tp;
  350.  
  351.     if (argc < 2) {
  352.         (void) strcat(line, " ");
  353.         printf("(local-files) ");
  354.         (void) gets(&line[strlen(line)]);
  355.         makeargv();
  356.         argc = margc;
  357.         argv = margv;
  358.     }
  359.     if (argc < 2) {
  360.         printf("usage:%s local-files\n", argv[0]);
  361.         code = -1;
  362.         return;
  363.     }
  364.     mname = argv[0];
  365.     mflag = 1;
  366.     oldintr = signal(SIGINT, mabort);
  367.     (void) setjmp(jabort);
  368.     if (proxy) {
  369.         char *cp, *tp2, tmpbuf[MAXPATHLEN];
  370.  
  371.         while ((cp = remglob(argv,0)) != NULL) {
  372.             if (*cp == 0) {
  373.                 mflag = 0;
  374.                 continue;
  375.             }
  376.             if (mflag && confirm(argv[0], cp)) {
  377.                 tp = cp;
  378.                 if (mcase) {
  379.                     while (*tp && !islower(*tp)) {
  380.                         tp++;
  381.                     }
  382.                     if (!*tp) {
  383.                         tp = cp;
  384.                         tp2 = tmpbuf;
  385.                         while ((*tp2 = *tp) != NULL) {
  386.                              if (isupper(*tp2)) {
  387.                                 *tp2 = 'a' + *tp2 - 'A';
  388.                              }
  389.                              tp++;
  390.                              tp2++;
  391.                         }
  392.                     }
  393.                     tp = tmpbuf;
  394.                 }
  395.                 if (ntflag) {
  396.                     tp = dotrans(tp);
  397.                 }
  398.                 if (mapflag) {
  399.                     tp = domap(tp);
  400.                 }
  401.                 sendrequest((sunique) ? "STOU" : "STOR",
  402.                     cp, tp, cp != tp || !interactive);
  403.                 if (!mflag && fromatty) {
  404.                     ointer = interactive;
  405.                     interactive = 1;
  406.                     if (confirm("Continue with","mput")) {
  407.                         mflag++;
  408.                     }
  409.                     interactive = ointer;
  410.                 }
  411.             }
  412.         }
  413.         (void) signal(SIGINT, oldintr);
  414.         mflag = 0;
  415.         return;
  416.     }
  417.     for (i = 1; i < argc; i++) {
  418.         register char **cpp, **gargs;
  419.  
  420.         if (!doglob) {
  421.             if (mflag && confirm(argv[0], argv[i])) {
  422.                 tp = (ntflag) ? dotrans(argv[i]) : argv[i];
  423.                 tp = (mapflag) ? domap(tp) : tp;
  424.                 sendrequest((sunique) ? "STOU" : "STOR",
  425.                     argv[i], tp, tp != argv[i] || !interactive);
  426.                 if (!mflag && fromatty) {
  427.                     ointer = interactive;
  428.                     interactive = 1;
  429.                     if (confirm("Continue with","mput")) {
  430.                         mflag++;
  431.                     }
  432.                     interactive = ointer;
  433.                 }
  434.             }
  435.             continue;
  436.         }
  437.         gargs = glob(argv[i]);
  438.         if (globerr != NULL) {
  439.             printf("%s\n", globerr);
  440.             if (gargs) {
  441.                 blkfree(gargs);
  442.                 free((char *)gargs);
  443.             }
  444.             continue;
  445.         }
  446.         for (cpp = gargs; cpp && *cpp != NULL; cpp++) {
  447.             if (mflag && confirm(argv[0], *cpp)) {
  448.                 tp = (ntflag) ? dotrans(*cpp) : *cpp;
  449.                 tp = (mapflag) ? domap(tp) : tp;
  450.                 sendrequest((sunique) ? "STOU" : "STOR",
  451.                     *cpp, tp, *cpp != tp || !interactive);
  452.                 if (!mflag && fromatty) {
  453.                     ointer = interactive;
  454.                     interactive = 1;
  455.                     if (confirm("Continue with","mput")) {
  456.                         mflag++;
  457.                     }
  458.                     interactive = ointer;
  459.                 }
  460.             }
  461.         }
  462.         if (gargs != NULL) {
  463.             blkfree(gargs);
  464.             free((char *)gargs);
  465.         }
  466.     }
  467.     (void) signal(SIGINT, oldintr);
  468.     mflag = 0;
  469. }
  470. #endif
  471.  
  472. reget(argc, argv)
  473.     char *argv[];
  474. {
  475.     (void) getit(argc, argv, 1, "r+w");
  476. }
  477.  
  478. get(argc, argv)
  479.     char *argv[];
  480. {
  481.     (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" );
  482. }
  483.  
  484. /*
  485.  * Receive one file.
  486.  */
  487. getit(argc, argv, restartit, mode)
  488.     char *argv[];
  489.     char *mode;
  490. {
  491.     int loc = 0;
  492.     char *oldargv1, *oldargv2;
  493.  
  494.     if (argc == 2) {
  495.         argc++;
  496.         argv[2] = argv[1];
  497.         loc++;
  498.     }
  499.     if (argc < 2) {
  500.         (void) strcat(line, " ");
  501.         printf("(remote-file) ");
  502.         (void) gets(&line[strlen(line)]);
  503.         makeargv();
  504.         argc = margc;
  505.         argv = margv;
  506.     }
  507.     if (argc < 2) {
  508. usage:
  509.         printf("usage: %s remote-file [ local-file ]\n", argv[0]);
  510.         code = -1;
  511.         return (0);
  512.     }
  513.     if (argc < 3) {
  514.         (void) strcat(line, " ");
  515.         printf("(local-file) ");
  516.         (void) gets(&line[strlen(line)]);
  517.         makeargv();
  518.         argc = margc;
  519.         argv = margv;
  520.     }
  521.     if (argc < 3) 
  522.         goto usage;
  523.     oldargv1 = argv[1];
  524.     oldargv2 = argv[2];
  525.     if (!globulize(&argv[2])) {
  526.         code = -1;
  527.         return (0);
  528.     }
  529.     if (loc && mcase) {
  530.         char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];
  531.  
  532.         while (*tp && !islower(*tp)) {
  533.             tp++;
  534.         }
  535.         if (!*tp) {
  536.             tp = argv[2];
  537.             tp2 = tmpbuf;
  538.             while ((*tp2 = *tp) != NULL) {
  539.                 if (isupper(*tp2)) {
  540.                     *tp2 = 'a' + *tp2 - 'A';
  541.                 }
  542.                 tp++;
  543.                 tp2++;
  544.             }
  545.             argv[2] = tmpbuf;
  546.         }
  547.     }
  548.     if (loc && ntflag)
  549.         argv[2] = dotrans(argv[2]);
  550.     if (loc && mapflag)
  551.         argv[2] = domap(argv[2]);
  552.     if (restartit) {
  553.         struct stat stbuf;
  554.         int ret;
  555.  
  556.         ret = stat(argv[2], &stbuf);
  557.         if (restartit == 1) {
  558.             if (ret < 0) {
  559.                 perror(argv[2]);
  560.                 return (0);
  561.             }
  562.             restart_point = stbuf.st_size;
  563.         } else {
  564.             if (ret == 0) {
  565.                 int overbose;
  566.  
  567.                 overbose = verbose;
  568.                 if (debug == 0)
  569.                     verbose = -1;
  570.                 if (command("MDTM %s", argv[1]) == COMPLETE) {
  571.                     int yy, mo, day, hour, min, sec;
  572.                     struct tm *tm;
  573.                     verbose = overbose;
  574.                     sscanf(reply_string,
  575.                         "%*s %04d%02d%02d%02d%02d%02d",
  576.                         &yy, &mo, &day, &hour, &min, &sec);
  577.                     tm = gmtime(&stbuf.st_mtime);
  578.                     tm->tm_mon++;
  579.                     if (tm->tm_year > yy%100)
  580.                         return (1);
  581.                     else if (tm->tm_year == yy%100) {
  582.                         if (tm->tm_mon > mo)
  583.                             return (1);
  584.                     } else if (tm->tm_mon == mo) {
  585.                         if (tm->tm_mday > day)
  586.                             return (1);
  587.                     } else if (tm->tm_mday == day) {
  588.                         if (tm->tm_hour > hour)
  589.                             return (1);
  590.                     } else if (tm->tm_hour == hour) {
  591.                         if (tm->tm_min > min)
  592.                             return (1);
  593.                     } else if (tm->tm_min == min) {
  594.                         if (tm->tm_sec > sec)
  595.                             return (1);
  596.                     }
  597.                 } else {
  598.                     printf("%s\n", reply_string);
  599.                     verbose = overbose;
  600.                     return (0);
  601.                 }
  602.             }
  603.         }
  604.     }
  605.  
  606.     recvrequest("RETR", argv[2], argv[1], mode,
  607.         argv[1] != oldargv1 || argv[2] != oldargv2);
  608.     restart_point = 0;
  609.     return (0);
  610. }
  611.  
  612. #if 0
  613. sig_t
  614. mabort()
  615. {
  616.     int ointer;
  617.     extern jmp_buf jabort;
  618.  
  619.     printf("\n");
  620.     (void) fflush(stdout);
  621.     if (mflag && fromatty) {
  622.         ointer = interactive;
  623.         interactive = 1;
  624.         if (confirm("Continue with", mname)) {
  625.             interactive = ointer;
  626.             longjmp(jabort,0);
  627.         }
  628.         interactive = ointer;
  629.     }
  630.     mflag = 0;
  631.     longjmp(jabort,0);
  632. }
  633. #endif
  634.  
  635. #if 0
  636. /*
  637.  * Get multiple files.
  638.  */
  639. mget(argc, argv)
  640.     char *argv[];
  641. {
  642.     char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN];
  643.     int ointer;
  644.     sig_t (*oldintr)(), mabort();
  645.     extern jmp_buf jabort;
  646.  
  647.     if (argc < 2) {
  648.         (void) strcat(line, " ");
  649.         printf("(remote-files) ");
  650.         (void) gets(&line[strlen(line)]);
  651.         makeargv();
  652.         argc = margc;
  653.         argv = margv;
  654.     }
  655.     if (argc < 2) {
  656.         printf("usage:%s remote-files\n", argv[0]);
  657.         code = -1;
  658.         return;
  659.     }
  660.     mname = argv[0];
  661.     mflag = 1;
  662.     oldintr = signal(SIGINT,mabort);
  663.     (void) setjmp(jabort);
  664.     while ((cp = remglob(argv,proxy)) != NULL) {
  665.         if (*cp == '\0') {
  666.             mflag = 0;
  667.             continue;
  668.         }
  669.         if (mflag && confirm(argv[0], cp)) {
  670.             tp = cp;
  671.             if (mcase) {
  672.                 while (*tp && !islower(*tp)) {
  673.                     tp++;
  674.                 }
  675.                 if (!*tp) {
  676.                     tp = cp;
  677.                     tp2 = tmpbuf;
  678.                     while ((*tp2 = *tp) != NULL) {
  679.                         if (isupper(*tp2)) {
  680.                             *tp2 = 'a' + *tp2 - 'A';
  681.                         }
  682.                         tp++;
  683.                         tp2++;
  684.                     }
  685.                 }
  686.                 tp = tmpbuf;
  687.             }
  688.             if (ntflag) {
  689.                 tp = dotrans(tp);
  690.             }
  691.             if (mapflag) {
  692.                 tp = domap(tp);
  693.             }
  694.             recvrequest("RETR", tp, cp, "w",
  695.                 tp != cp || !interactive);
  696.             if (!mflag && fromatty) {
  697.                 ointer = interactive;
  698.                 interactive = 1;
  699.                 if (confirm("Continue with","mget")) {
  700.                     mflag++;
  701.                 }
  702.                 interactive = ointer;
  703.             }
  704.         }
  705.     }
  706.     (void) signal(SIGINT,oldintr);
  707.     mflag = 0;
  708. }
  709. #endif
  710.  
  711. char *
  712. remglob(argv,doswitch)
  713.     char *argv[];
  714.     int doswitch;
  715. {
  716.     char temp[16];
  717.     static char buf[MAXPATHLEN];
  718.     static FILE *ftemp = NULL;
  719.     static char **args;
  720.     int oldverbose, oldhash;
  721.     char *cp, *mode;
  722.  
  723.     if (!mflag) {
  724.         if (!doglob) {
  725.             args = NULL;
  726.         }
  727.         else {
  728.             if (ftemp) {
  729.                 (void) fclose(ftemp);
  730.                 ftemp = NULL;
  731.             }
  732.         }
  733.         return(NULL);
  734.     }
  735.     if (!doglob) {
  736.         if (args == NULL)
  737.             args = argv;
  738.         if ((cp = *++args) == NULL)
  739.             args = NULL;
  740.         return (cp);
  741.     }
  742.     if (ftemp == NULL) {
  743.         (void) sprintf(temp, "T:TMPftp.%08lX",FindTask(0L));
  744.         oldverbose = verbose, verbose = 0;
  745.         oldhash = hash, hash = 0;
  746.         if (doswitch) {
  747.             pswitch(!proxy);
  748.         }
  749.         for (mode = "w"; *++argv != NULL; mode = "a")
  750.             recvrequest ("NLST", temp, *argv, mode, 0);
  751.         if (doswitch) {
  752.             pswitch(!proxy);
  753.         }
  754.         verbose = oldverbose; hash = oldhash;
  755.         ftemp = fopen(temp, "r");
  756.         if (ftemp == NULL) {
  757.             printf("can't find list of remote files, oops\n");
  758.             return (NULL);
  759.         }
  760.     }
  761.     if (fgets(buf, sizeof (buf), ftemp) == NULL) {
  762.         (void) fclose(ftemp), ftemp = NULL;
  763.         (void) unlink(temp);
  764.         return (NULL);
  765.     }
  766.     if ((cp = index(buf, '\n')) != NULL)
  767.         *cp = '\0';
  768.     return (buf);
  769. }
  770.  
  771. char *
  772. onoff(bool)
  773.     int bool;
  774. {
  775.  
  776.     return (bool ? "on" : "off");
  777. }
  778.  
  779. /*
  780.  * Show status.
  781.  */
  782. /*ARGSUSED*/
  783. status(argc, argv)
  784.     char *argv[];
  785. {
  786.     int i;
  787.  
  788.     if (connected)
  789.         printf("Connected to %s.\n", hostname);
  790.     else
  791.         printf("Not connected.\n");
  792.     if (!proxy) {
  793.         pswitch(1);
  794.         if (connected) {
  795.             printf("Connected for proxy commands to %s.\n", hostname);
  796.         }
  797.         else {
  798.             printf("No proxy connection.\n");
  799.         }
  800.         pswitch(0);
  801.     }
  802.     printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
  803.         modename, typename, formname, structname);
  804.     printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 
  805.         onoff(verbose), onoff(bell), onoff(interactive),
  806.         onoff(doglob));
  807.     printf("Store unique: %s; Receive unique: %s\n", onoff(sunique),
  808.         onoff(runique));
  809.     printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag));
  810.     if (ntflag) {
  811.         printf("Ntrans: (in) %s (out) %s\n", ntin,ntout);
  812.     }
  813.     else {
  814.         printf("Ntrans: off\n");
  815.     }
  816.     if (mapflag) {
  817.         printf("Nmap: (in) %s (out) %s\n", mapin, mapout);
  818.     }
  819.     else {
  820.         printf("Nmap: off\n");
  821.     }
  822.     printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
  823.         onoff(hash), onoff(sendport));
  824.     if (macnum > 0) {
  825.         printf("Macros:\n");
  826.         for (i=0; i<macnum; i++) {
  827.             printf("\t%s\n",macros[i].mac_name);
  828.         }
  829.     }
  830.     code = 0;
  831. }
  832.  
  833. /*
  834.  * Set beep on cmd completed mode.
  835.  */
  836. /*VARARGS*/
  837. setbell()
  838. {
  839.  
  840.     bell = !bell;
  841.     printf("Bell mode %s.\n", onoff(bell));
  842.     code = bell;
  843. }
  844.  
  845. /*
  846.  * Turn on packet tracing.
  847.  */
  848. /*VARARGS*/
  849. settrace()
  850. {
  851.  
  852.     trace = !trace;
  853.     printf("Packet tracing %s.\n", onoff(trace));
  854.     code = trace;
  855. }
  856.  
  857. /*
  858.  * Toggle hash mark printing during transfers.
  859.  */
  860. /*VARARGS*/
  861. sethash()
  862. {
  863.  
  864.     hash = !hash;
  865.     printf("Hash mark printing %s", onoff(hash));
  866.     code = hash;
  867.     if (hash)
  868.         printf(" (%d bytes/hash mark)", 1024);
  869.     printf(".\n");
  870. }
  871.  
  872. /*
  873.  * Turn on printing of server echo's.
  874.  */
  875. /*VARARGS*/
  876. setverbose()
  877. {
  878.  
  879.     verbose = !verbose;
  880.     printf("Verbose mode %s.\n", onoff(verbose));
  881.     code = verbose;
  882. }
  883.  
  884. /*
  885.  * Toggle PORT cmd use before each data connection.
  886.  */
  887. /*VARARGS*/
  888. setport()
  889. {
  890.  
  891.     sendport = !sendport;
  892.     printf("Use of PORT cmds %s.\n", onoff(sendport));
  893.     code = sendport;
  894. }
  895.  
  896. /*
  897.  * Turn on interactive prompting
  898.  * during mget, mput, and mdelete.
  899.  */
  900. /*VARARGS*/
  901. setprompt()
  902. {
  903.  
  904.     interactive = !interactive;
  905.     printf("Interactive mode %s.\n", onoff(interactive));
  906.     code = interactive;
  907. }
  908.  
  909. /*
  910.  * Toggle metacharacter interpretation
  911.  * on local file names.
  912.  */
  913. /*VARARGS*/
  914. setglob()
  915. {
  916.     
  917.     doglob = !doglob;
  918.     printf("Globbing %s.\n", onoff(doglob));
  919.     code = doglob;
  920. }
  921.  
  922. /*
  923.  * Set debugging mode on/off and/or
  924.  * set level of debugging.
  925.  */
  926. /*VARARGS*/
  927. setdebug(argc, argv)
  928.     char *argv[];
  929. {
  930.     int val;
  931.  
  932.     if (argc > 1) {
  933.         val = atoi(argv[1]);
  934.         if (val < 0) {
  935.             printf("%s: bad debugging value.\n", argv[1]);
  936.             code = -1;
  937.             return;
  938.         }
  939.     } else
  940.         val = !debug;
  941.     debug = val;
  942.     if (debug)
  943.         options |= SO_DEBUG;
  944.     else
  945.         options &= ~SO_DEBUG;
  946.     printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
  947.     code = debug > 0;
  948. }
  949.  
  950. /*
  951.  * Set current working directory
  952.  * on remote machine.
  953.  */
  954. cd(argc, argv)
  955.     char *argv[];
  956. {
  957.  
  958.     if (argc < 2) {
  959.         (void) strcat(line, " ");
  960.         printf("(remote-directory) ");
  961.         (void) gets(&line[strlen(line)]);
  962.         makeargv();
  963.         argc = margc;
  964.         argv = margv;
  965.     }
  966.     if (argc < 2) {
  967.         printf("usage:%s remote-directory\n", argv[0]);
  968.         code = -1;
  969.         return;
  970.     }
  971.     if (command("CWD %s", argv[1]) == ERROR && code == 500) {
  972.         if (verbose)
  973.             printf("CWD command not recognized, trying XCWD\n");
  974.         (void) command("XCWD %s", argv[1]);
  975.     }
  976. }
  977.  
  978. /*
  979.  * Set current working directory
  980.  * on local machine.
  981.  */
  982. lcd(argc, argv)
  983.     char *argv[];
  984. {
  985.     char buf[MAXPATHLEN + 1];
  986.     extern char *getcwd();
  987.  
  988.     if (argc < 2)
  989.         argc++, argv[1] = home;
  990.     if (argc != 2) {
  991.         printf("usage:%s local-directory\n", argv[0]);
  992.         code = -1;
  993.         return;
  994.     }
  995.     if (!globulize(&argv[1])) {
  996.         code = -1;
  997.         return;
  998.     }
  999.     if (chdir(argv[1]) < 0) {
  1000.         perror(argv[1]);
  1001.         code = -1;
  1002.         return;
  1003.     }
  1004.     printf("Local directory now %s\n", getcwd(buf, MAXPATHLEN + 1));
  1005.     code = 0;
  1006. }
  1007.  
  1008. /*
  1009.  * Delete a single file.
  1010.  */
  1011. delete(argc, argv)
  1012.     char *argv[];
  1013. {
  1014.  
  1015.     if (argc < 2) {
  1016.         (void) strcat(line, " ");
  1017.         printf("(remote-file) ");
  1018.         (void) gets(&line[strlen(line)]);
  1019.         makeargv();
  1020.         argc = margc;
  1021.         argv = margv;
  1022.     }
  1023.     if (argc < 2) {
  1024.         printf("usage:%s remote-file\n", argv[0]);
  1025.         code = -1;
  1026.         return;
  1027.     }
  1028.     (void) command("DELE %s", argv[1]);
  1029. }
  1030.  
  1031. #if 0
  1032. /*
  1033.  * Delete multiple files.
  1034.  */
  1035. mdelete(argc, argv)
  1036.     char *argv[];
  1037. {
  1038.     char *cp;
  1039.     int ointer;
  1040.     sig_t (*oldintr)(), mabort();
  1041.     extern jmp_buf jabort;
  1042.  
  1043.     if (argc < 2) {
  1044.         (void) strcat(line, " ");
  1045.         printf("(remote-files) ");
  1046.         (void) gets(&line[strlen(line)]);
  1047.         makeargv();
  1048.         argc = margc;
  1049.         argv = margv;
  1050.     }
  1051.     if (argc < 2) {
  1052.         printf("usage:%s remote-files\n", argv[0]);
  1053.         code = -1;
  1054.         return;
  1055.     }
  1056.     mname = argv[0];
  1057.     mflag = 1;
  1058.     oldintr = signal(SIGINT, mabort);
  1059.     (void) setjmp(jabort);
  1060.     while ((cp = remglob(argv,0)) != NULL) {
  1061.         if (*cp == '\0') {
  1062.             mflag = 0;
  1063.             continue;
  1064.         }
  1065.         if (mflag && confirm(argv[0], cp)) {
  1066.             (void) command("DELE %s", cp);
  1067.             if (!mflag && fromatty) {
  1068.                 ointer = interactive;
  1069.                 interactive = 1;
  1070.                 if (confirm("Continue with", "mdelete")) {
  1071.                     mflag++;
  1072.                 }
  1073.                 interactive = ointer;
  1074.             }
  1075.         }
  1076.     }
  1077.     (void) signal(SIGINT, oldintr);
  1078.     mflag = 0;
  1079. }
  1080. #endif
  1081. /*
  1082.  * Rename a remote file.
  1083.  */
  1084. renamefile(argc, argv)
  1085.     char *argv[];
  1086. {
  1087.  
  1088.     if (argc < 2) {
  1089.         (void) strcat(line, " ");
  1090.         printf("(from-name) ");
  1091.         (void) gets(&line[strlen(line)]);
  1092.         makeargv();
  1093.         argc = margc;
  1094.         argv = margv;
  1095.     }
  1096.     if (argc < 2) {
  1097. usage:
  1098.         printf("%s from-name to-name\n", argv[0]);
  1099.         code = -1;
  1100.         return;
  1101.     }
  1102.     if (argc < 3) {
  1103.         (void) strcat(line, " ");
  1104.         printf("(to-name) ");
  1105.         (void) gets(&line[strlen(line)]);
  1106.         makeargv();
  1107.         argc = margc;
  1108.         argv = margv;
  1109.     }
  1110.     if (argc < 3) 
  1111.         goto usage;
  1112.     if (command("RNFR %s", argv[1]) == CONTINUE)
  1113.         (void) command("RNTO %s", argv[2]);
  1114. }
  1115.  
  1116. /*
  1117.  * Get a directory listing
  1118.  * of remote files.
  1119.  */
  1120. ls(argc, argv)
  1121.     char *argv[];
  1122. {
  1123.     char *cmd;
  1124.  
  1125.     if (argc < 2)
  1126.         argc++, argv[1] = NULL;
  1127.     if (argc < 3)
  1128.         argc++, argv[2] = "-";
  1129.     if (argc > 3) {
  1130.         printf("usage: %s remote-directory local-file\n", argv[0]);
  1131.         code = -1;
  1132.         return;
  1133.     }
  1134.     cmd = argv[0][0] == 'n' ? "NLST" : "LIST";
  1135.     if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
  1136.         code = -1;
  1137.         return;
  1138.     }
  1139.     if (strcmp(argv[2], "-") && *argv[2] != '|')
  1140.         if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) {
  1141.             code = -1;
  1142.             return;
  1143.     }
  1144.     recvrequest(cmd, argv[2], argv[1], "w", 0);
  1145. }
  1146.  
  1147. #if 0
  1148. /*
  1149.  * Get a directory listing
  1150.  * of multiple remote files.
  1151.  */
  1152. mls(argc, argv)
  1153.     char *argv[];
  1154. {
  1155.     char *cmd, mode[1], *dest;
  1156.     int ointer, i;
  1157.     sig_t (*oldintr)(), mabort();
  1158.     extern jmp_buf jabort;
  1159.  
  1160.     if (argc < 2) {
  1161.         (void) strcat(line, " ");
  1162.         printf("(remote-files) ");
  1163.         (void) gets(&line[strlen(line)]);
  1164.         makeargv();
  1165.         argc = margc;
  1166.         argv = margv;
  1167.     }
  1168.     if (argc < 3) {
  1169.         (void) strcat(line, " ");
  1170.         printf("(local-file) ");
  1171.         (void) gets(&line[strlen(line)]);
  1172.         makeargv();
  1173.         argc = margc;
  1174.         argv = margv;
  1175.     }
  1176.     if (argc < 3) {
  1177.         printf("usage:%s remote-files local-file\n", argv[0]);
  1178.         code = -1;
  1179.         return;
  1180.     }
  1181.     dest = argv[argc - 1];
  1182.     argv[argc - 1] = NULL;
  1183.     if (strcmp(dest, "-") && *dest != '|')
  1184.         if (!globulize(&dest) || !confirm("output to local-file:", dest)) {
  1185.             code = -1;
  1186.             return;
  1187.     }
  1188.     cmd = argv[0][1] == 'l' ? "NLST" : "LIST";
  1189.     mname = argv[0];
  1190.     mflag = 1;
  1191.     oldintr = signal(SIGINT, mabort);
  1192.     (void) setjmp(jabort);
  1193.     for (i = 1; mflag && i < argc-1; ++i) {
  1194.         *mode = (i == 1) ? 'w' : 'a';
  1195.         recvrequest(cmd, dest, argv[i], mode, 0);
  1196.         if (!mflag && fromatty) {
  1197.             ointer = interactive;
  1198.             interactive = 1;
  1199.             if (confirm("Continue with", argv[0])) {
  1200.                 mflag ++;
  1201.             }
  1202.             interactive = ointer;
  1203.         }
  1204.     }
  1205.     (void) signal(SIGINT, oldintr);
  1206.     mflag = 0;
  1207. }
  1208. #endif
  1209.  
  1210. #if 0
  1211. /*
  1212.  * Do a shell escape
  1213.  */
  1214. /*ARGSUSED*/
  1215. shell(argc, argv)
  1216.     char *argv[];
  1217. {
  1218.     int pid;
  1219.     sig_t (*old1)(), (*old2)();
  1220.     char shellnam[40], *shell, *namep; 
  1221.     union wait status;
  1222.  
  1223.     old1 = signal (SIGINT, SIG_IGN);
  1224.     old2 = signal (SIGQUIT, SIG_IGN);
  1225.     if ((pid = fork()) == 0) {
  1226.         for (pid = 3; pid < 20; pid++)
  1227.             (void) close(pid);
  1228.         (void) signal(SIGINT, SIG_DFL);
  1229.         (void) signal(SIGQUIT, SIG_DFL);
  1230.         shell = getenv("SHELL");
  1231.         if (shell == NULL)
  1232.             shell = _PATH_BSHELL;
  1233.         namep = rindex(shell,'/');
  1234.         if (namep == NULL)
  1235.             namep = shell;
  1236.         (void) strcpy(shellnam,"-");
  1237.         (void) strcat(shellnam, ++namep);
  1238.         if (strcmp(namep, "sh") != 0)
  1239.             shellnam[0] = '+';
  1240.         if (debug) {
  1241.             printf ("%s\n", shell);
  1242.             (void) fflush (stdout);
  1243.         }
  1244.         if (argc > 1) {
  1245.             execl(shell,shellnam,"-c",altarg,(char *)0);
  1246.         }
  1247.         else {
  1248.             execl(shell,shellnam,(char *)0);
  1249.         }
  1250.         perror(shell);
  1251.         code = -1;
  1252.         exit(1);
  1253.         }
  1254.     if (pid > 0)
  1255.         while (wait(&status) != pid)
  1256.             ;
  1257.     (void) signal(SIGINT, old1);
  1258.     (void) signal(SIGQUIT, old2);
  1259.     if (pid == -1) {
  1260.         perror("Try again later");
  1261.         code = -1;
  1262.     }
  1263.     else {
  1264.         code = 0;
  1265.     }
  1266.     return (0);
  1267. }
  1268. #endif
  1269.  
  1270. /*
  1271.  * Send new user information (re-login)
  1272.  */
  1273. user(argc, argv)
  1274.     int argc;
  1275.     char **argv;
  1276. {
  1277.     char acct[80], *getpass();
  1278.     int n, aflag = 0;
  1279.  
  1280.     if (argc < 2) {
  1281.         (void) strcat(line, " ");
  1282.         printf("(username) ");
  1283.         (void) gets(&line[strlen(line)]);
  1284.         makeargv();
  1285.         argc = margc;
  1286.         argv = margv;
  1287.     }
  1288.     if (argc > 4) {
  1289.         printf("usage: %s username [password] [account]\n", argv[0]);
  1290.         code = -1;
  1291.         return (0);
  1292.     }
  1293.     n = command("USER %s", argv[1]);
  1294.     if (n == CONTINUE) {
  1295.         if (argc < 3 )
  1296.             argv[2] = getpass("Password: "), argc++;
  1297.         n = command("PASS %s", argv[2]);
  1298.     }
  1299.     if (n == CONTINUE) {
  1300.         if (argc < 4) {
  1301.             printf("Account: "); (void) fflush(stdout);
  1302.             (void) fgets(acct, sizeof(acct) - 1, stdin);
  1303.             acct[strlen(acct) - 1] = '\0';
  1304.             argv[3] = acct; argc++;
  1305.         }
  1306.         n = command("ACCT %s", argv[3]);
  1307.         aflag++;
  1308.     }
  1309.     if (n != COMPLETE) {
  1310.         fprintf(stdout, "Login failed.\n");
  1311.         return (0);
  1312.     }
  1313.     if (!aflag && argc == 4) {
  1314.         (void) command("ACCT %s", argv[3]);
  1315.     }
  1316.     return (1);
  1317. }
  1318.  
  1319. /*
  1320.  * Print working directory.
  1321.  */
  1322. /*VARARGS*/
  1323. pwd()
  1324. {
  1325.     int oldverbose = verbose;
  1326.  
  1327.     /*
  1328.      * If we aren't verbose, this doesn't do anything!
  1329.      */
  1330.     verbose = 1;
  1331.     if (command("PWD") == ERROR && code == 500) {
  1332.         printf("PWD command not recognized, trying XPWD\n");
  1333.         (void) command("XPWD");
  1334.     }
  1335.     verbose = oldverbose;
  1336. }
  1337.  
  1338. /*
  1339.  * Make a directory.
  1340.  */
  1341. makedir(argc, argv)
  1342.     char *argv[];
  1343. {
  1344.  
  1345.     if (argc < 2) {
  1346.         (void) strcat(line, " ");
  1347.         printf("(directory-name) ");
  1348.         (void) gets(&line[strlen(line)]);
  1349.         makeargv();
  1350.         argc = margc;
  1351.         argv = margv;
  1352.     }
  1353.     if (argc < 2) {
  1354.         printf("usage: %s directory-name\n", argv[0]);
  1355.         code = -1;
  1356.         return;
  1357.     }
  1358.     if (command("MKD %s", argv[1]) == ERROR && code == 500) {
  1359.         if (verbose)
  1360.             printf("MKD command not recognized, trying XMKD\n");
  1361.         (void) command("XMKD %s", argv[1]);
  1362.     }
  1363. }
  1364.  
  1365. /*
  1366.  * Remove a directory.
  1367.  */
  1368. removedir(argc, argv)
  1369.     char *argv[];
  1370. {
  1371.  
  1372.     if (argc < 2) {
  1373.         (void) strcat(line, " ");
  1374.         printf("(directory-name) ");
  1375.         (void) gets(&line[strlen(line)]);
  1376.         makeargv();
  1377.         argc = margc;
  1378.         argv = margv;
  1379.     }
  1380.     if (argc < 2) {
  1381.         printf("usage: %s directory-name\n", argv[0]);
  1382.         code = -1;
  1383.         return;
  1384.     }
  1385.     if (command("RMD %s", argv[1]) == ERROR && code == 500) {
  1386.         if (verbose)
  1387.             printf("RMD command not recognized, trying XRMD\n");
  1388.         (void) command("XRMD %s", argv[1]);
  1389.     }
  1390. }
  1391.  
  1392. /*
  1393.  * Send a line, verbatim, to the remote machine.
  1394.  */
  1395. quote(argc, argv)
  1396.     char *argv[];
  1397. {
  1398.     int i;
  1399.     char buf[BUFSIZ];
  1400.  
  1401.     if (argc < 2) {
  1402.         (void) strcat(line, " ");
  1403.         printf("(command line to send) ");
  1404.         (void) gets(&line[strlen(line)]);
  1405.         makeargv();
  1406.         argc = margc;
  1407.         argv = margv;
  1408.     }
  1409.     if (argc < 2) {
  1410.         printf("usage: %s line-to-send\n", argv[0]);
  1411.         code = -1;
  1412.         return;
  1413.     }
  1414.     (void) strcpy(buf, argv[1]);
  1415.     for (i = 2; i < argc; i++) {
  1416.         (void) strcat(buf, " ");
  1417.         (void) strcat(buf, argv[i]);
  1418.     }
  1419.     if (command(buf) == PRELIM) {
  1420.         while (getreply(0) == PRELIM);
  1421.     }
  1422. }
  1423.  
  1424. /*
  1425.  * Send a SITE command to the remote machine.  The line
  1426.  * is sent almost verbatim to the remote machine, the
  1427.  * first argument is changed to SITE.
  1428.  */
  1429.  
  1430. site(argc, argv)
  1431.     char *argv[];
  1432. {
  1433.     int i;
  1434.     char buf[BUFSIZ];
  1435.  
  1436.     if (argc < 2) {
  1437.         (void) strcat(line, " ");
  1438.         printf("(arguments to SITE command) ");
  1439.         (void) gets(&line[strlen(line)]);
  1440.         makeargv();
  1441.         argc = margc;
  1442.         argv = margv;
  1443.     }
  1444.     if (argc < 2) {
  1445.         printf("usage: %s line-to-send\n", argv[0]);
  1446.         code = -1;
  1447.         return;
  1448.     }
  1449.     (void) strcpy(buf, "SITE ");
  1450.     (void) strcat(buf, argv[1]);
  1451.     for (i = 2; i < argc; i++) {
  1452.         (void) strcat(buf, " ");
  1453.         (void) strcat(buf, argv[i]);
  1454.     }
  1455.     if (command(buf) == PRELIM) {
  1456.         while (getreply(0) == PRELIM);
  1457.     }
  1458. }
  1459.  
  1460. do_chmod(argc, argv)
  1461.     char *argv[];
  1462. {
  1463.     if (argc == 2) {
  1464.         printf("usage: %s mode file-name\n", argv[0]);
  1465.         code = -1;
  1466.         return;
  1467.     }
  1468.     if (argc < 3) {
  1469.         (void) strcat(line, " ");
  1470.         printf("(mode and file-name) ");
  1471.         (void) gets(&line[strlen(line)]);
  1472.         makeargv();
  1473.         argc = margc;
  1474.         argv = margv;
  1475.     }
  1476.     if (argc != 3) {
  1477.         printf("usage: %s mode file-name\n", argv[0]);
  1478.         code = -1;
  1479.         return;
  1480.     }
  1481.     (void)command("SITE CHMOD %s %s", argv[1], argv[2]);
  1482. }
  1483.  
  1484. do_umask(argc, argv)
  1485.     char *argv[];
  1486. {
  1487.     int oldverbose = verbose;
  1488.  
  1489.     verbose = 1;
  1490.     (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
  1491.     verbose = oldverbose;
  1492. }
  1493.  
  1494. idle(argc, argv)
  1495.     char *argv[];
  1496. {
  1497.     int oldverbose = verbose;
  1498.  
  1499.     verbose = 1;
  1500.     (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
  1501.     verbose = oldverbose;
  1502. }
  1503.  
  1504. /*
  1505.  * Ask the other side for help.
  1506.  */
  1507. rmthelp(argc, argv)
  1508.     char *argv[];
  1509. {
  1510.     int oldverbose = verbose;
  1511.  
  1512.     verbose = 1;
  1513.     (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
  1514.     verbose = oldverbose;
  1515. }
  1516.  
  1517. /*
  1518.  * Terminate session and exit.
  1519.  */
  1520. /*VARARGS*/
  1521. quit()
  1522. {
  1523.  
  1524.     if (connected)
  1525.         disconnect();
  1526.     pswitch(1);
  1527.     if (connected) {
  1528.         disconnect();
  1529.     }
  1530.     exit(0);
  1531. }
  1532.  
  1533. /*
  1534.  * Terminate session, but don't exit.
  1535.  */
  1536. disconnect()
  1537. {
  1538.     extern int cout;
  1539.     extern int data;
  1540.  
  1541.     if (!connected)
  1542.         return;
  1543. #ifdef FTP_LOG_USAGE
  1544.     syslog(LOG_INFO, "FTP LOGIN disconnected");
  1545. #endif /* FTP_LOG_USAGE */
  1546.     (void) command("QUIT");
  1547.     if (cout != -1) {
  1548.         (void) s_close(cout);
  1549.     }
  1550.     cout = -1;
  1551.     connected = 0;
  1552.     data = -1;
  1553.     if (!proxy) {
  1554.         macnum = 0;
  1555.     }
  1556. }
  1557.  
  1558. confirm(cmd, file)
  1559.     char *cmd, *file;
  1560. {
  1561.     char line[BUFSIZ];
  1562.  
  1563.     if (!interactive)
  1564.         return (1);
  1565.     printf("%s %s? ", cmd, file);
  1566.     (void) fflush(stdout);
  1567.     (void) gets(line);
  1568.     return (*line != 'n' && *line != 'N');
  1569. }
  1570.  
  1571. fatal(msg)
  1572.     char *msg;
  1573. {
  1574.  
  1575.     fprintf(stderr, "ftp: %s\n", msg);
  1576.     exit(1);
  1577. }
  1578.  
  1579. /*
  1580.  * Glob a local file name specification with
  1581.  * the expectation of a single return value.
  1582.  * Can't control multiple values being expanded
  1583.  * from the expression, we return only the first.
  1584.  */
  1585. globulize(cpp)
  1586.     char **cpp;
  1587. {
  1588.     char **globbed;
  1589.  
  1590.     if (!doglob)
  1591.         return (1);
  1592.     globbed = glob(*cpp);
  1593.     if (globerr != NULL) {
  1594.         printf("%s: %s\n", *cpp, globerr);
  1595.         if (globbed) {
  1596.             blkfree(globbed);
  1597.             free((char *)globbed);
  1598.         }
  1599.         return (0);
  1600.     }
  1601.     if (globbed) {
  1602.         *cpp = *globbed++;
  1603.         /* don't waste too much memory */
  1604.         if (*globbed) {
  1605.             blkfree(globbed);
  1606.             free((char *)globbed);
  1607.         }
  1608.     }
  1609.     return (1);
  1610. }
  1611.  
  1612. account(argc,argv)
  1613.     int argc;
  1614.     char **argv;
  1615. {
  1616.     char acct[50], *getpass(), *ap;
  1617.  
  1618.     if (argc > 1) {
  1619.         ++argv;
  1620.         --argc;
  1621.         (void) strncpy(acct,*argv,49);
  1622.         acct[49] = '\0';
  1623.         while (argc > 1) {
  1624.             --argc;
  1625.             ++argv;
  1626.             (void) strncat(acct,*argv, 49-strlen(acct));
  1627.         }
  1628.         ap = acct;
  1629.     }
  1630.     else {
  1631.         ap = getpass("Account:");
  1632.     }
  1633.     (void) command("ACCT %s", ap);
  1634. }
  1635.  
  1636. #if 0
  1637. jmp_buf abortprox;
  1638.  
  1639. sig_t
  1640. proxabort()
  1641. {
  1642.     extern int proxy;
  1643.  
  1644.     if (!proxy) {
  1645.         pswitch(1);
  1646.     }
  1647.     if (connected) {
  1648.         proxflag = 1;
  1649.     }
  1650.     else {
  1651.         proxflag = 0;
  1652.     }
  1653.     pswitch(0);
  1654.     longjmp(abortprox,1);
  1655. }
  1656.  
  1657. doproxy(argc,argv)
  1658.     int argc;
  1659.     char *argv[];
  1660. {
  1661.     sig_t (*oldintr)(), proxabort();
  1662.     register struct cmd *c;
  1663.     struct cmd *getcmd();
  1664.     extern struct cmd cmdtab[];
  1665.     extern jmp_buf abortprox;
  1666.  
  1667.     if (argc < 2) {
  1668.         (void) strcat(line, " ");
  1669.         printf("(command) ");
  1670.         (void) gets(&line[strlen(line)]);
  1671.         makeargv();
  1672.         argc = margc;
  1673.         argv = margv;
  1674.     }
  1675.     if (argc < 2) {
  1676.         printf("usage:%s command\n", argv[0]);
  1677.         code = -1;
  1678.         return;
  1679.     }
  1680.     c = getcmd(argv[1]);
  1681.     if (c == (struct cmd *) -1) {
  1682.         printf("?Ambiguous command\n");
  1683.         (void) fflush(stdout);
  1684.         code = -1;
  1685.         return;
  1686.     }
  1687.     if (c == 0) {
  1688.         printf("?Invalid command\n");
  1689.         (void) fflush(stdout);
  1690.         code = -1;
  1691.         return;
  1692.     }
  1693.     if (!c->c_proxy) {
  1694.         printf("?Invalid proxy command\n");
  1695.         (void) fflush(stdout);
  1696.         code = -1;
  1697.         return;
  1698.     }
  1699.     if (setjmp(abortprox)) {
  1700.         code = -1;
  1701.         return;
  1702.     }
  1703.     oldintr = signal(SIGINT, proxabort);
  1704.     pswitch(1);
  1705.     if (c->c_conn && !connected) {
  1706.         printf("Not connected\n");
  1707.         (void) fflush(stdout);
  1708.         pswitch(0);
  1709.         (void) signal(SIGINT, oldintr);
  1710.         code = -1;
  1711.         return;
  1712.     }
  1713.     (*c->c_handler)(argc-1, argv+1);
  1714.     if (connected) {
  1715.         proxflag = 1;
  1716.     }
  1717.     else {
  1718.         proxflag = 0;
  1719.     }
  1720.     pswitch(0);
  1721.     (void) signal(SIGINT, oldintr);
  1722. }
  1723. #endif
  1724.  
  1725. setcase()
  1726. {
  1727.     mcase = !mcase;
  1728.     printf("Case mapping %s.\n", onoff(mcase));
  1729.     code = mcase;
  1730. }
  1731.  
  1732. setcr()
  1733. {
  1734.     crflag = !crflag;
  1735.     printf("Carriage Return stripping %s.\n", onoff(crflag));
  1736.     code = crflag;
  1737. }
  1738.  
  1739. setntrans(argc,argv)
  1740.     int argc;
  1741.     char *argv[];
  1742. {
  1743.     if (argc == 1) {
  1744.         ntflag = 0;
  1745.         printf("Ntrans off.\n");
  1746.         code = ntflag;
  1747.         return;
  1748.     }
  1749.     ntflag++;
  1750.     code = ntflag;
  1751.     (void) strncpy(ntin, argv[1], 16);
  1752.     ntin[16] = '\0';
  1753.     if (argc == 2) {
  1754.         ntout[0] = '\0';
  1755.         return;
  1756.     }
  1757.     (void) strncpy(ntout, argv[2], 16);
  1758.     ntout[16] = '\0';
  1759. }
  1760.  
  1761. char *
  1762. dotrans(name)
  1763.     char *name;
  1764. {
  1765.     static char new[MAXPATHLEN];
  1766.     char *cp1, *cp2 = new;
  1767.     register int i, ostop, found;
  1768.  
  1769.     for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++);
  1770.     for (cp1 = name; *cp1; cp1++) {
  1771.         found = 0;
  1772.         for (i = 0; *(ntin + i) && i < 16; i++) {
  1773.             if (*cp1 == *(ntin + i)) {
  1774.                 found++;
  1775.                 if (i < ostop) {
  1776.                     *cp2++ = *(ntout + i);
  1777.                 }
  1778.                 break;
  1779.             }
  1780.         }
  1781.         if (!found) {
  1782.             *cp2++ = *cp1;
  1783.         }
  1784.     }
  1785.     *cp2 = '\0';
  1786.     return(new);
  1787. }
  1788.  
  1789. setnmap(argc, argv)
  1790.     int argc;
  1791.     char *argv[];
  1792. {
  1793.     char *cp;
  1794.  
  1795.     if (argc == 1) {
  1796.         mapflag = 0;
  1797.         printf("Nmap off.\n");
  1798.         code = mapflag;
  1799.         return;
  1800.     }
  1801.     if (argc < 3) {
  1802.         (void) strcat(line, " ");
  1803.         printf("(mapout) ");
  1804.         (void) gets(&line[strlen(line)]);
  1805.         makeargv();
  1806.         argc = margc;
  1807.         argv = margv;
  1808.     }
  1809.     if (argc < 3) {
  1810.         printf("Usage: %s [mapin mapout]\n",argv[0]);
  1811.         code = -1;
  1812.         return;
  1813.     }
  1814.     mapflag = 1;
  1815.     code = 1;
  1816.     cp = index(altarg, ' ');
  1817.     if (proxy) {
  1818.         while(*++cp == ' ');
  1819.         altarg = cp;
  1820.         cp = index(altarg, ' ');
  1821.     }
  1822.     *cp = '\0';
  1823.     (void) strncpy(mapin, altarg, MAXPATHLEN - 1);
  1824.     while (*++cp == ' ');
  1825.     (void) strncpy(mapout, cp, MAXPATHLEN - 1);
  1826. }
  1827.  
  1828. char *
  1829. domap(name)
  1830.     char *name;
  1831. {
  1832.     static char new[MAXPATHLEN];
  1833.     register char *cp1 = name, *cp2 = mapin;
  1834.     char *tp[9], *te[9];
  1835.     int i, toks[9], toknum = 0, match = 1;
  1836.  
  1837.     for (i=0; i < 9; ++i) {
  1838.         toks[i] = 0;
  1839.     }
  1840.     while (match && *cp1 && *cp2) {
  1841.         switch (*cp2) {
  1842.             case '\\':
  1843.                 if (*++cp2 != *cp1) {
  1844.                     match = 0;
  1845.                 }
  1846.                 break;
  1847.             case '$':
  1848.                 if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
  1849.                     if (*cp1 != *(++cp2+1)) {
  1850.                         toks[toknum = *cp2 - '1']++;
  1851.                         tp[toknum] = cp1;
  1852.                         while (*++cp1 && *(cp2+1)
  1853.                             != *cp1);
  1854.                         te[toknum] = cp1;
  1855.                     }
  1856.                     cp2++;
  1857.                     break;
  1858.                 }
  1859.                 /* FALLTHROUGH */
  1860.             default:
  1861.                 if (*cp2 != *cp1) {
  1862.                     match = 0;
  1863.                 }
  1864.                 break;
  1865.         }
  1866.         if (match && *cp1) {
  1867.             cp1++;
  1868.         }
  1869.         if (match && *cp2) {
  1870.             cp2++;
  1871.         }
  1872.     }
  1873.     if (!match && *cp1) /* last token mismatch */
  1874.     {
  1875.         toks[toknum] = 0;
  1876.     }
  1877.     cp1 = new;
  1878.     *cp1 = '\0';
  1879.     cp2 = mapout;
  1880.     while (*cp2) {
  1881.         match = 0;
  1882.         switch (*cp2) {
  1883.             case '\\':
  1884.                 if (*(cp2 + 1)) {
  1885.                     *cp1++ = *++cp2;
  1886.                 }
  1887.                 break;
  1888.             case '[':
  1889. LOOP:
  1890.                 if (*++cp2 == '$' && isdigit(*(cp2+1))) { 
  1891.                     if (*++cp2 == '0') {
  1892.                         char *cp3 = name;
  1893.  
  1894.                         while (*cp3) {
  1895.                             *cp1++ = *cp3++;
  1896.                         }
  1897.                         match = 1;
  1898.                     }
  1899.                     else if (toks[toknum = *cp2 - '1']) {
  1900.                         char *cp3 = tp[toknum];
  1901.  
  1902.                         while (cp3 != te[toknum]) {
  1903.                             *cp1++ = *cp3++;
  1904.                         }
  1905.                         match = 1;
  1906.                     }
  1907.                 }
  1908.                 else {
  1909.                     while (*cp2 && *cp2 != ',' && 
  1910.                         *cp2 != ']') {
  1911.                         if (*cp2 == '\\') {
  1912.                             cp2++;
  1913.                         }
  1914.                         else if (*cp2 == '$' &&
  1915.                                    isdigit(*(cp2+1))) {
  1916.                             if (*++cp2 == '0') {
  1917.                                char *cp3 = name;
  1918.  
  1919.                                while (*cp3) {
  1920.                                 *cp1++ = *cp3++;
  1921.                                }
  1922.                             }
  1923.                             else if (toks[toknum =
  1924.                                 *cp2 - '1']) {
  1925.                                char *cp3=tp[toknum];
  1926.  
  1927.                                while (cp3 !=
  1928.                                   te[toknum]) {
  1929.                                 *cp1++ = *cp3++;
  1930.                                }
  1931.                             }
  1932.                         }
  1933.                         else if (*cp2) {
  1934.                             *cp1++ = *cp2++;
  1935.                         }
  1936.                     }
  1937.                     if (!*cp2) {
  1938.                         printf("nmap: unbalanced brackets\n");
  1939.                         return(name);
  1940.                     }
  1941.                     match = 1;
  1942.                     cp2--;
  1943.                 }
  1944.                 if (match) {
  1945.                     while (*++cp2 && *cp2 != ']') {
  1946.                           if (*cp2 == '\\' && *(cp2 + 1)) {
  1947.                             cp2++;
  1948.                           }
  1949.                     }
  1950.                     if (!*cp2) {
  1951.                         printf("nmap: unbalanced brackets\n");
  1952.                         return(name);
  1953.                     }
  1954.                     break;
  1955.                 }
  1956.                 switch (*++cp2) {
  1957.                     case ',':
  1958.                         goto LOOP;
  1959.                     case ']':
  1960.                         break;
  1961.                     default:
  1962.                         cp2--;
  1963.                         goto LOOP;
  1964.                 }
  1965.                 break;
  1966.             case '$':
  1967.                 if (isdigit(*(cp2 + 1))) {
  1968.                     if (*++cp2 == '0') {
  1969.                         char *cp3 = name;
  1970.  
  1971.                         while (*cp3) {
  1972.                             *cp1++ = *cp3++;
  1973.                         }
  1974.                     }
  1975.                     else if (toks[toknum = *cp2 - '1']) {
  1976.                         char *cp3 = tp[toknum];
  1977.  
  1978.                         while (cp3 != te[toknum]) {
  1979.                             *cp1++ = *cp3++;
  1980.                         }
  1981.                     }
  1982.                     break;
  1983.                 }
  1984.                 /* intentional drop through */
  1985.             default:
  1986.                 *cp1++ = *cp2;
  1987.                 break;
  1988.         }
  1989.         cp2++;
  1990.     }
  1991.     *cp1 = '\0';
  1992.     if (!*new) {
  1993.         return(name);
  1994.     }
  1995.     return(new);
  1996. }
  1997.  
  1998. setsunique()
  1999. {
  2000.     sunique = !sunique;
  2001.     printf("Store unique %s.\n", onoff(sunique));
  2002.     code = sunique;
  2003. }
  2004.  
  2005. setrunique()
  2006. {
  2007.     runique = !runique;
  2008.     printf("Receive unique %s.\n", onoff(runique));
  2009.     code = runique;
  2010. }
  2011.  
  2012. /* change directory to perent directory */
  2013. cdup()
  2014. {
  2015.     if (command("CDUP") == ERROR && code == 500) {
  2016.         if (verbose)
  2017.             printf("CDUP command not recognized, trying XCUP\n");
  2018.         (void) command("XCUP");
  2019.     }
  2020. }
  2021.  
  2022. /* restart transfer at specific point */
  2023. restart(argc, argv)
  2024.     int argc;
  2025.     char *argv[];
  2026. {
  2027.     extern long atol();
  2028.     if (argc != 2)
  2029.         printf("restart: offset not specified\n");
  2030.     else {
  2031.         restart_point = atol(argv[1]);
  2032.         printf("restarting at %ld. %s\n", restart_point,
  2033.             "execute get, put or append to initiate transfer");
  2034.     }
  2035. }
  2036.  
  2037. /* show remote system type */
  2038. syst()
  2039. {
  2040.     (void) command("SYST");
  2041. }
  2042.  
  2043. macdef(argc, argv)
  2044.     int argc;
  2045.     char *argv[];
  2046. {
  2047.     char *tmp;
  2048.     int c;
  2049.  
  2050.     if (macnum == 16) {
  2051.         printf("Limit of 16 macros have already been defined\n");
  2052.         code = -1;
  2053.         return;
  2054.     }
  2055.     if (argc < 2) {
  2056.         (void) strcat(line, " ");
  2057.         printf("(macro name) ");
  2058.         (void) gets(&line[strlen(line)]);
  2059.         makeargv();
  2060.         argc = margc;
  2061.         argv = margv;
  2062.     }
  2063.     if (argc != 2) {
  2064.         printf("Usage: %s macro_name\n",argv[0]);
  2065.         code = -1;
  2066.         return;
  2067.     }
  2068.     if (interactive) {
  2069.         printf("Enter macro line by line, terminating it with a null line\n");
  2070.     }
  2071.     (void) strncpy(macros[macnum].mac_name, argv[1], 8);
  2072.     if (macnum == 0) {
  2073.         macros[macnum].mac_start = macbuf;
  2074.     }
  2075.     else {
  2076.         macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
  2077.     }
  2078.     tmp = macros[macnum].mac_start;
  2079.     while (tmp != macbuf+4096) {
  2080.         if ((c = getchar()) == EOF) {
  2081.             printf("macdef:end of file encountered\n");
  2082.             code = -1;
  2083.             return;
  2084.         }
  2085.         if ((*tmp = c) == '\n') {
  2086.             if (tmp == macros[macnum].mac_start) {
  2087.                 macros[macnum++].mac_end = tmp;
  2088.                 code = 0;
  2089.                 return;
  2090.             }
  2091.             if (*(tmp-1) == '\0') {
  2092.                 macros[macnum++].mac_end = tmp - 1;
  2093.                 code = 0;
  2094.                 return;
  2095.             }
  2096.             *tmp = '\0';
  2097.         }
  2098.         tmp++;
  2099.     }
  2100.     while (1) {
  2101.         while ((c = getchar()) != '\n' && c != EOF)
  2102.             /* LOOP */;
  2103.         if (c == EOF || getchar() == '\n') {
  2104.             printf("Macro not defined - 4k buffer exceeded\n");
  2105.             code = -1;
  2106.             return;
  2107.         }
  2108.     }
  2109. }
  2110.  
  2111. /*
  2112.  * get size of file on remote machine
  2113.  */
  2114. sizecmd(argc, argv)
  2115.     char *argv[];
  2116. {
  2117.  
  2118.     if (argc < 2) {
  2119.         (void) strcat(line, " ");
  2120.         printf("(filename) ");
  2121.         (void) gets(&line[strlen(line)]);
  2122.         makeargv();
  2123.         argc = margc;
  2124.         argv = margv;
  2125.     }
  2126.     if (argc < 2) {
  2127.         printf("usage:%s filename\n", argv[0]);
  2128.         code = -1;
  2129.         return;
  2130.     }
  2131.     (void) command("SIZE %s", argv[1]);
  2132. }
  2133.  
  2134. /*
  2135.  * get last modification time of file on remote machine
  2136.  */
  2137. modtime(argc, argv)
  2138.     char *argv[];
  2139. {
  2140.     int overbose;
  2141.  
  2142.     if (argc < 2) {
  2143.         (void) strcat(line, " ");
  2144.         printf("(filename) ");
  2145.         (void) gets(&line[strlen(line)]);
  2146.         makeargv();
  2147.         argc = margc;
  2148.         argv = margv;
  2149.     }
  2150.     if (argc < 2) {
  2151.         printf("usage:%s filename\n", argv[0]);
  2152.         code = -1;
  2153.         return;
  2154.     }
  2155.     overbose = verbose;
  2156.     if (debug == 0)
  2157.         verbose = -1;
  2158.     if (command("MDTM %s", argv[1]) == COMPLETE) {
  2159.         int yy, mo, day, hour, min, sec;
  2160.         sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
  2161.             &day, &hour, &min, &sec);
  2162.         /* might want to print this in local time */
  2163.         printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
  2164.             mo, day, yy, hour, min, sec);
  2165.     } else
  2166.         printf("%s\n", reply_string);
  2167.     verbose = overbose;
  2168. }
  2169.  
  2170. /*
  2171.  * show status on reomte machine
  2172.  */
  2173. rmtstatus(argc, argv)
  2174.     char *argv[];
  2175. {
  2176.     (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
  2177. }
  2178.  
  2179. /*
  2180.  * get file if modtime is more recent than current file
  2181.  */
  2182. newer(argc, argv)
  2183.     char *argv[];
  2184. {
  2185.     if (getit(argc, argv, -1, "w"))
  2186.         printf("Local file \"%s\" is newer than remote file \"%s\"\n",
  2187.             argv[1], argv[2]);
  2188. }
  2189.